#!/bin/bash
#THIS DRIVER WRITTEN FOR THE BAM 1020, FOR THE PURPOSE OF DATA COLLECTION
#FOR QUESTIONS WRITE mailto:mvona@arb.ca.gov
#UPDATE: ;
#-------------------------------------------------------------
#THIS FUNCTION DETERMINES THE ABSOLUTE PATH TO THIS BAM DRIVER
DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# THIS IS THE FUNCTION CALLED IN THE EVENT THAT CTRL+C IS PRESSED
cleanup()
{
   echo "Caught Signal ... cleaning up."
   if !(rm -f Data/.locked > /dev/null); then
      {
         exit 1
      }
   fi
   echo "Done cleanup ... quitting."
   exit 1
}
#THE DIAGNOSTIC DATA (DIAG) ROUTINE TAKES THE DATA STREAM FROM THE API 400E
#AND TESTS FOR THE RECOGNITION OF KEY WORDS IN EACH LINE OF OUTPUT.
#IF THE KEY WORD IS DETECTED ON THAT LINE, A TEST IS PERFORMED.
#IF THE TEST SUGGESTS THAT AN ERROR CONDITION EXISTS BASED UPON THE ALLOWABLE
#RANGES SPECIFIED BY THE ARB CHECK-SHEET, THE OFFENDING LINE IS WRITTEN OUT
#TO A FILE IN THE Data DIRECTORY. THE NAME OF THE DESTINATION FILE IS
#errors{HH}. THE FILES CAN THEN BE PARSED AND UTILIZED BY ANY ALERT PROGRAM?DAEMON.
diag()
{
   thishour=`date "+%H"`
   lasthour=`date -d "last hour" "+%H"`
   thisalert="errors$thishour"
   #MAKE SURE TO ESCAPE THE PERIOD
   echo "$data2" > "${DIR}/.${thishour}_${instance}_bam_config"
   this_point=$(echo "$data" | awk 'BEGIN {FS=","}{tot=$10+$11+$12+$13+$14+$15+$16+$17+$18+$19+$20}{ print tot }')
   if [ "$this_point" -gt "0" ]; then
      {
         echo "$rprt_nm has experienced an error: $data" >> "Data/${thisalert}"
         these_errors=''
         #The error list in this BAM is reported with the oldest first.
         #So we dump it to a file and reverse sort first.
         #sleep 2
      }
   fi
   if [ -e ${DIR}/.${lasthour}_${instance}_bam_config ]; then
      {
         diff_count=$(diff "${DIR}/.${lasthour}_${instance}_bam_config" "${DIR}/.${thishour}_${instance}_bam_config" | wc -l)
         if [ "${diff_count}" -gt "8" ]; then
            echo "$rprt_nm ${occurence} configuration changed from ${lasthour} to ${thishour}: " > ${DIR}/.bamcfgdlta_${instance}_${thishour}
            echo "$rprt_nm ${occurence} configuration at ${lasthour} : " >> ${DIR}/.bamcfgdlta_${instance}_${thishour}
            echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" >> ${DIR}/.bamcfgdlta_${instance}_${thishour}
            cat "${DIR}/.${lasthour}_${instance}_bam_config" | awk 'NF>0 { print }' >> ${DIR}/.bamcfgdlta_${instance}_${thishour}
            echo "$rprt_nm ${occurence} configuration at ${thishour} : " >> ${DIR}/.bamcfgdlta_${instance}_${thishour}
            echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" >> ${DIR}/.bamcfgdlta_${instance}_${thishour}
            cat "${DIR}/.${thishour}_${instance}_bam_config" | awk 'NF>0 { print }' >> ${DIR}/.bamcfgdlta_${instance}_${thishour}
            echo "$rprt_nm ${occurence} configuration has changed. See the attached details." >> "Data/${thisalert}"
            
         fi
      }
   fi
}

#BEGIN WRITE
#THIS FUNCTION HANDLES READ RIGHT HANDSHAKES BETWEEN VARIOUS DRIVERS
#IN GENERAL, THE DATA IS PLACED IN THE VARIABLE $TIMESTAMP PRIOR TO CALL
#NEXT, IT OPENS THE DATA DIRECTORY AND LOOKS FOR THE .locked FILE
#IF IT EXISTS, IT HANGS OUT UNTIL IT DOESN'T EXIST. AT THAT POINT
#IT CREATES A .locked FILE, AND APPENDS TO THE DATA RECORD.
#FINALLY IT REMOVES THE .locked FILE IT HAS CREATED.
#THIS FUNCTION ALSO PARSES THE .DISABLED FILE IN THE DRIVER FOLDER
#AND TAKES A CHANNEL OFF LINE BY PRE-PENDING --DISABLED-- TO EACH LINE OF CONTENT IN THE DATA DIRECTORY
#written by MJV
write()
{
   #CONFIRM THAT THERE IS NO HIDDEN FILE CALLED '.locked'
   while [ -e "Data/.locked" ];
   do
      sleep .2;
   done
   echo "LOCKED" > "Data/.locked";
   this_alert="errors$thishour"
   #PARSE THE .disabled File
   channel_status=`cat "$DIR/.disabled${instance}"`
   #IF THE FILE DOSEN'T EXIT OR IS NOT ACCESIBLE
   #MAKES SURE A VALUE OF 0 IS USED
   if [ `expr $channel_status + 0` -eq 1 ]; then
      if !(echo "$data" | awk -v oc=$occurrence -v ts=$timestamp '{ print ts "BAM"oc"="$3*1000 " QTOT"oc"="$4" " $5" " $6 $7 $8 $9 $10 $1 " " $2 " --DISABLED--"}'>> "Data/$datafile"); then
         {
            echo "GENERAL FAILURE WRITING TO RECORD: $#";
            cleanup;
         }
      fi
      
      if !(echo "$data2" | sed 's/^/'$timestamp2'/g'| grep -v \:\:\:\$ | sed 's/$/'\-\-DISABLED\-\-'/g' >> "Data/$datafile" ); then
         {
            echo "GENERAL FAILURE WRITING TO RECORD: $#";
            cleanup;
         }
      fi
      
   else
      ####################################################ROUTINE TO VERIFY NON_NULL DATA##############################
      # CARBLOGGER APPLIES A CORRECTION FACTOR OF 1000 FOR AQSB to BAM DATA TO TRANSLATE FROM UG TO MG. 		#
      # AN UNFORTUNATE CONSEQUENCE OF THIS IS THAT AWK WILL INTERPRET (1000)*(NULL) AS 0. THIS FUNCTION		#
      # WILL NOT APPLY THIS FACTOR IF A NULL VALUE IF PASSED								#
      #################################################################################################################
      
      if [ -z `echo "$data" | awk '{RS=","}{ print $3 }'` ]; then
         {
            echo "${timestamp}${rprt_nm}${occurrence} null detected...maybe the CARBLogger was unplugged... " >> "Data/${this_alert}"
            echo "${timestamp}${rprt_nm}${occurrence} may be disconnected BAM${occurrence}=999 " >> "Data/${datafile}"
         }
      else
         { # | sed "s/^/${timestamp}BAM${occurrence}=/g"
            if !(echo "$data" | awk -v oc=$occurrence -v ts=$timestamp '{ print ts "BAM"oc"="$3*1000 " QTOT"oc"="$4" " $5" " $6 $7 $8 $9 $10 $1 " " $2 }' >> "Data/${datafile}"); then
               {
                  echo "GENERAL FAILURE WRITING TO RECORD: $#";
                  cleanup;
               }
            fi
            if !(echo "$data2" | sed 's/^/'$timestamp2'/g'| grep -v \:\:\:\$ >> "Data/$datafile" ); then
               {
                  echo "GENERAL FAILURE WRITING TO RECORD: $#";
                  cleanup;
               }
            fi
         }
      fi
      
   fi
   if !(rm -f "Data/.locked" > /dev/null ); then
      {
         echo "GENERAL FAILURE REMOVING LOCK: $#";
         exit 1;
      }
   fi
   if !(timestamp="" && data="" && data2="" ); then
      {
         echo "GENERAL FAILURE CLEARING WRITE BUFFER: $#";
         cleanup;
      }
   fi
}
talk()
{
   
   #Date stamp
   today=`date "+%Y-%d-%m"`
   timestamp=$rprt_nm::`date "+%m-%d-%Y_%H:%M"`:::
   timestamp2=$rprt_nm::CONFIG::`date "+%m-%d-%Y_%H:%M"`:::
   #THIS IS THE NAME OF THE DATA FILE RIGHT NOW
   datafile="$saroad-$today"
   #TALK TO THE INSTRUMENT, PRE-APPEND THE TIME-STAMP AND REPORTING NAME TO EACH
   #LINE OF OUTPUT AND tee TO THE DATA FILE. FOR THE BAM, WE DO THIS TWICE AN HOUR.
   #THE FIRST TIME WE GRAB LAST HOURS DATA. THE SECOND TIME WE GRAB THE INSTRUMENT CONFIG
   data=`timeout 20 sjinn -d $dvc_prt -s $cmnd1 -w $wt_rsp1 -b $bd_rt -r$rsp_lngth $dtr $ctr $p8n1 | grep -e ^[0-9][0-9]\/[0-3][0-9]\/[0-9][0-9]`
   sleep 2
   data2=`timeout 20 sjinn -d $dvc_prt -s "\p\r\r\r\4" -w 4 -b $bd_rt -r910 $dtr $ctr $p8n1`
   if [ -z `echo "$data" | awk '{RS=","}{ print $3 }'` ]; then
      {
         sleep 60
         data=`timeout 20 sjinn -d $dvc_prt -s $cmnd1 -w $wt_rsp1 -b $bd_rt -r$rsp_lngth $dtr $ctr $p8n1 | grep -e ^[0-9][0-9]\/[0-3][0-9]\/[0-9][0-9]`
         sleep 2
         data2=`timeout 20 sjinn -d $dvc_prt -s "\p\r\r\r\4" -w 4 -b $bd_rt -r910 $dtr $ctr $p8n1`
         if [ -z `echo "$data" | awk '{RS=","}{ print $3 }'` ]; then
            {
               sleep 60
               data=`timeout 20 sjinn -d $dvc_prt -s $cmnd1 -w $wt_rsp1 -b $bd_rt -r$rsp_lngth $dtr $ctr $p8n1 | grep -e ^[0-9][0-9]\/[0-3][0-9]\/[0-9][0-9]`
               sleep 2
               data2=`timeout 20 sjinn -d $dvc_prt -s "\p\r\r\r\4" -w 4 -b $bd_rt -r910 $dtr $ctr $p8n1`
               
               if [ -z `echo "$data" | awk '{RS=","}{ print $3 }'` ]; then
                  {
                     sleep 60
                     data=`timeout 20 sjinn -d $dvc_prt -s $cmnd1 -w $wt_rsp1 -b $bd_rt -r$rsp_lngth $dtr $ctr $p8n1 | grep -e ^[0-9][0-9]\/[0-3][0-9]\/[0-9][0-9]`
                     sleep 2
                     data2=`timeout 20 sjinn -d $dvc_prt -s "\p\r\r\r\4" -w 4 -b $bd_rt -r910 $dtr $ctr $p8n1`
                     
                  }
               fi
            }
         fi
      }
   fi
   
   
}
#THIS IS THE ACTUAL COMMUNICATION WITH THE INSTRUMENT
#THE TIMER CONTROL. AT THE BEGINNING IT TESTS FOR THE
#EXISTENCE IF TOGGLE VARIABLES WHICH ARE UTILIZED BOTH BY
#THE COMM ROUTINE runit() AND THE DIAGNOSTICS DATA ROUTINE
#diag()
runit()
{
   #IF THE -d, -C, or -p variable is set to on, then append those parameters
   #to the sjinn communication string. If the -i parameter is passed, diag will
   #test for IZS specific routines.
   if [ "$dtr_val" = "on" ]; then
      dtr="--dtr"
   fi
   if [ "$ctr_val" = "on" ]; then
      ctr="--ctr"
   fi
   if [ "$p8n1_val" = "on" ]; then
      p8n1="-p8n1"
   fi
   #Date stamp
   talk
   write
   diag
}
#THIS IS THE FUNCTION RUN IN THE EVENT THAT THE REQUIRED PARAMETERS
#ARE NOT ENTERED.
usage()
{
   clear
cat << EOF
usage: $0 options
OPTIONS:
-h	display help
-r	rprt_nm [rn]
-d	dvc_prt [eg, /dev/ttyS0, /dev/ttyPS0, /dev/ttyUSB1] 
-b	bd_rt [2400,4800,9600,etc.]
-c	cmnd1 (e.g, \r\r\r\p\6\4)
-m	min_val [two digit minute to run on EVERY HOUR]
-w	wt_rsp1 [seconds]
-l	rsp_lngth [characters]
-o	occurrence
-s	SAROAD number of the station
-t	[on/off] (OPTIONAL)
-C	[on/off] (OPTIONAL)
-p	[on/off] (OPTIONAL)
Last updated 9/10/2009
EOF
}
#HELP FUNCTION GIVES BACKGROUND ON THIS DRIVER
help_me ()
{
   clear
   cat .help
   exit 0
}
def_opts ()
{
   clear
   cat .options
}

##CLEAR ALL VARIABLES
rprt_nm= ; dvc_prt= ; bd_rt= ; cmnd1= ; wt_rsp1= ; bd_rt= ; rsp_lngth= ;
dvc_prt= ; frqncy= ; dtr= ; ctr= ; p8n1= ; izs= ; saroad= ; p8n1= ; run_min= ;
instance=1 ; occurrence= ;
##INITIALIZE THE BUFFER
return='NOT WRITTEN TO'
##loop through all variables and parameters
##Note that the position of the colon indicates the presence
##of a parameter to collect. The h parameter simply
##returns the help message.

while getopts “hr:s:d:b:c:w:l:t:C:p:m:I:o:” OPTION
do
   case $OPTION in
      s)
         saroad=$OPTARG
      ;;
      r)
         rprt_nm=$OPTARG
      ;;
      d)
         dvc_prt=$OPTARG
      ;;
      b)
         bd_rt=$OPTARG
      ;;
      c)
         cmnd1=$OPTARG
      ;;
      w)
         wt_rsp1=$OPTARG
      ;;
      l)
         rsp_lngth=$OPTARG
      ;;
      t)
         dtr_val=$OPTARG
      ;;
      C)
         ctr_val=$OPTARG
      ;;
      p)
         p8n1_val=$OPTARG
      ;;
      m)
         run_min=$OPTARG
      ;;
      o)
         occurrence=$OPTARG
      ;;
      I)
         instance=$OPTARG
      ;;
      h)
         help_me
         exit 1
      ;;
      *)
         usage
         exit 1
      ;;
   esac
done
#CHECK FOR THE CRITICAL PARAMETERS, IF THEY ARE NOT PRESENT THEN
#RUN THE USAGE FUNCTION WHICH RETURNS THE INSTRUCTIONS FOR PROPER USAGE
#MUST HAVE r n d b c w l i s
if [ -z "$rprt_nm" ] || [ -z "$dvc_prt" ] || [ -z "$bd_rt" ] || [ -z "$cmnd1" ] ||
[ -z "$wt_rsp1" ] || [ -z "$rsp_lngth" ] || [ -z "$saroad" ] || [ -z "$run_min" ]
then
   {
      usage
      exit
   }
fi
#INITIALIZED THE RAN VARIABLE. THIS IS USED TO TOGGLE THE TIMER GATE
ran=0
#TRAP CTRL+C
trap cleanup 1 2 3 6 15
#SETUP THE OPERATING LOOP
while :
do
   #SET THE MINUTE VARIABLE
   minute=`date "+%M"`
   #IF THE MINUTE VALUE IS THE TERM SPECIFIED, BEGIN RUNNING
   if [ "$minute" -eq "$run_min" ] && [ "$ran" -eq "0" ]; then
      {
         #RUN THE RUNIT FUNCTION
         runit
         #TOGGLE THE RAN VARIABLE SO THAT THE PROCESS WILL NOT REPEAT
         #UNTIL THE BEGINNING OF THE NEXT MINUTE.
         ran=1
         #WAIT FOR COMPLETION OF THE RUNIT FUNCTION AND THE VARIABLE
         #SET
         sleep 60
      }
      #IF THE SECOND VALUE IS GREATER THAT 02, RESET RAN TO 0
      #AND WAIT ONE SECOND BEFORE CHECKING AGAIN
   else
      {
         #WAIT 15 SEC
         sleep 15
         #SET RAN TO 0
         ran=0
      }
   fi
done;
exit;

